#include "mat2.h"
#include "dmat2.h"

namespace libvec
{
  dmat2::dmat2()
  {
    dvec2 v(0);

    this->v1 = v;
    this->v2 = v;
  }

  dmat2::dmat2(mat2 m)
  {
    this->v1 = m.v1;
    this->v2 = m.v2;
  }

  dmat2::dmat2(double value)
  {
    this->v1.x = value;
    this->v2.y = value;
  }

  dmat2::dmat2(double n11, double n12, double n21, double n22)
  {
    this->v1.x = n11;
    this->v2.x = n12;

    this->v1.y = n21;
    this->v2.y = n22;
  }

  dmat2::dmat2(dvec2 v1, dvec2 v2)
  {
    this->v1 = v1;
    this->v2 = v2;
  }

  dvec2 &dmat2::operator[](int index)
  {
    static dvec2 empty;

    switch (index)
    {
      case 0:
        return this->v1;

      case 1:
        return this->v2;
    }

    return empty;
  }

  dmat2 dmat2::operator=(dmat2 m)
  {
    this->v1 = m.v1;
    this->v2 = m.v2;

    return *this;
  }

  bool dmat2::operator==(dmat2 m)
  {
    return (this->v1 == m.v1) && (this->v2 == m.v2);
  }

  bool dmat2::operator!=(dmat2 m)
  {
    return (this->v1 != m.v1) || (this->v2 != m.v2);
  }

  dmat2 &dmat2::operator+()
  {
    return *this;
  }

  dmat2 &dmat2::operator-()
  {
    static dmat2 out;

    out.v1 = -this->v1;
    out.v2 = -this->v2;

    return out;
  }

  dmat2 dmat2::operator+(dmat2 m)
  {
    static dmat2 out;

    out.v1 = this->v1 + m.v1;
    out.v2 = this->v2 + m.v2;

    return out;
  }

  dmat2 dmat2::operator+=(dmat2 m)
  {
    this->v1 += m.v1;
    this->v2 += m.v2;

    return *this;
  }

  dmat2 dmat2::operator-(dmat2 m)
  {
    static dmat2 out;

    out.v1 = this->v1 - m.v1;
    out.v2 = this->v2 - m.v2;

    return out;
  }

  dmat2 dmat2::operator-=(dmat2 m)
  {
    this->v1 -= m.v1;
    this->v2 -= m.v2;

    return *this;
  }

  dvec2 dmat2::operator*(dvec2 v)
  {
    static dvec2 out;

    out.x = this->v1.x*v.x + this->v2.x*v.y;
    out.y = this->v1.y*v.x + this->v2.y*v.y;

    return out;
  }

  dmat2 dmat2::operator*(dmat2 m)
  {
    static dmat2 out;

    out.v1.x = this->v1.x*m.v1.x + this->v2.x*m.v1.y;
    out.v2.x = this->v1.x*m.v2.x + this->v2.x*m.v2.y;

    out.v1.y = this->v1.y*m.v1.x + this->v2.y*m.v1.y;
    out.v2.y = this->v1.y*m.v2.x + this->v2.y*m.v2.y;

    return out;
  }

  dmat2 dmat2::operator*=(dmat2 m)
  {
    static dmat2 out;

    out.v1.x = this->v1.x*m.v1.x + this->v2.x*m.v1.y;
    out.v2.x = this->v1.x*m.v2.x + this->v2.x*m.v2.y;

    out.v1.y = this->v1.y*m.v1.x + this->v2.y*m.v1.y;
    out.v2.y = this->v1.y*m.v2.x + this->v2.y*m.v2.y;

    this->v1 = out.v1;
    this->v2 = out.v2;

    return out;
  }

  dmat2 dmat2::operator*(double scale)
  {
    static dmat2 out;

    out.v1 = this->v1 * scale;
    out.v2 = this->v2 * scale;

    return out;
  }

  dmat2 dmat2::operator*=(double scale)
  {
    this->v1 *= scale;
    this->v2 *= scale;

    return *this;
  }

  dmat2 dmat2::operator/(double scale)
  {
    static dmat2 out;

    out.v1 = this->v1 / scale;
    out.v2 = this->v2 / scale;

    return out;
  }

  dmat2 dmat2::operator/=(double scale)
  {
    this->v1 /= scale;
    this->v2 /= scale;

    return *this;
  }
}

